package com.deductive.service.special.special_import.service;


import com.deductive.service.special.SpecialTableColumnService;
import com.deductive.service.special.special_import.tool.LayerInfo;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

@Service
@Slf4j
public class GdalService {
    private List<String> successUrls = new ArrayList<>();

    public List<String> getSuccessUrls() {
        return successUrls;
    }
    private static final Logger logger = LoggerFactory.getLogger(GdalService.class);

    @Value("${postgresql.dbname}")
    private String dbName;

    @Value("${postgresql.username}")
    private String dbUsername;

    @Value("${postgresql.password}")
    private String dbPassword;
    @Value("${postgresql.host}")
    private String dbHost;
    @Value("${postgresql.port}")
    private int dbPort;

    @Value("${ogrinfo}")
    private String ogrinfo;

    @Value("${ogr2ogr}")
    private String ogr2ogr;

    @Autowired
    private GeoserverPublishService geoserverPublishService;

    @Autowired
    private PgServiceImpl pgService;

    @Autowired
    private SpecialTableColumnService desdTableColumnService;



    private String publishToGeoserver(String workspace, String storeName, String layerName, String geometryType,String epsg) throws IOException {
        return geoserverPublishService.publishLayer(workspace, storeName, layerName, geometryType,epsg);
    }

    /**
     * 获取GDB中的图层信息，包括图层名称和几何类型
     *
     * @param gdbPath GDB文件路径
     * @return 图层信息列表
     */
    public List<LayerInfo> getLayersFromGdb(String gdbPath) {
        List<LayerInfo> layers = new ArrayList<>();
        try {
            String command = String.format(ogrinfo, gdbPath);
            ProcessBuilder processBuilder = new ProcessBuilder(command.split(" "));
            processBuilder.redirectErrorStream(true);
            Process process = processBuilder.start();

            String currentLayer = null;
            String geometryType = null;
            String epsg = null;
            String count = null;
            double minX = 0, minY = 0, maxX = 0, maxY = 0;

            try (BufferedReader reader = new BufferedReader(
                    new InputStreamReader(process.getInputStream()))) {
                String line;
                while ((line = reader.readLine()) != null) {
                    // 获取图层名称
                    if (line.startsWith("Layer name:")) {
                        // 如果之前有图层信息，保存它
                        if (currentLayer != null && geometryType != null) {
                            LayerInfo layerInfo = new LayerInfo(currentLayer, geometryType, epsg);
                            layerInfo.setMinX(minX);
                            layerInfo.setMinY(minY);
                            layerInfo.setMaxX(maxX);
                            layerInfo.setMaxY(maxY);
                            layers.add(layerInfo);
                        }
                        currentLayer = line.split(":")[1].trim();
                        geometryType = null;
                        epsg = null;
                        minX = minY = maxX = maxY = 0;
                    }
                    // 获取几何类型
                    else if (line.trim().startsWith("Geometry:")) {

                        geometryType = line.split(":")[1].trim();
                        //判断是否有空格
                        if (geometryType.contains(" ")) {
                            geometryType = geometryType.replace(" ", "");
                        }
                    }
                    // 获取EPSG代码
                    else if (line.contains("ID[\"EPSG\",")) {
                        epsg = line.substring(line.indexOf(",")+1, line.indexOf("]]"));

                    }
                    // 获取Extent信息
                    else if (line.trim().startsWith("Extent:")) {
                        // 格式通常为：Extent: (minX, minY) - (maxX, maxY)
                        String[] coordinates = line.substring(line.indexOf("(")).split("\\) - \\(");
                        String[] min = coordinates[0].substring(1).split(",");
                        String[] max = coordinates[1].substring(0, coordinates[1].length() - 1).split(",");
                        minX = Double.parseDouble(min[0].trim());
                        minY = Double.parseDouble(min[1].trim());
                        maxX = Double.parseDouble(max[0].trim());
                        maxY = Double.parseDouble(max[1].trim());
                    }
                    // 获取数据数量
                    else if (line.trim().startsWith("Feature Count:")) {
                      count = line.split(": ")[1];
                    }
                }
                // 添加最后一个图层的信息
                if (currentLayer != null && geometryType != null) {
                    LayerInfo layerInfo = new LayerInfo(currentLayer, geometryType, epsg);
                    layerInfo.setCount(count);
                    layerInfo.setMinX(minX);
                    layerInfo.setMinY(minY);
                    layerInfo.setMaxX(maxX);
                    layerInfo.setMaxY(maxY);
                    layers.add(layerInfo);
                }
            }

            int exitCode = process.waitFor();
            if (exitCode != 0) {
                log.error("获取图层信息失败，退出代码：{}", exitCode);
            }

        } catch (Exception e) {
            log.error("获取GDB图层信息时发生错误", e);
            throw new RuntimeException("获取图层信息失败: " + e.getMessage());
        }
        return layers;
    }


    /**
     * 上传GDB到PostgreSQL
     *
     * @param gdbPath    GDB文件路径
     * @param layerInfos 图层信息列表
     * @return 是否全部上传成功
     */
    public boolean uploadGdbToPostgres(String gdbPath, List<LayerInfo> layerInfos) {
        try {
            boolean allSuccess = true;

            for (LayerInfo layerInfo : layerInfos) {
                try {
                    // 从数据库URL中提取数据库名称
//                    String dbName = extractDatabaseName(dbUrl);

                    // 构建ogr2ogr命令
                    String command = String.format(
                            ogr2ogr,
                            dbName, dbUsername, dbPassword, dbHost, dbPort,
                            gdbPath, layerInfo.getLayerName(),
                            mapGeometryType(layerInfo.getGeometryType())
                    );

                    log.info("正在处理图层: {}, 几何类型: {}",
                            layerInfo.getLayerName(),
                            layerInfo.getGeometryType());

                    ProcessBuilder processBuilder = new ProcessBuilder(command.split(" "));
                    processBuilder.redirectErrorStream(true);
                    Process process = processBuilder.start();

                    // 读取进程输出
                    StringBuilder output = new StringBuilder();
                    try (BufferedReader reader = new BufferedReader(
                            new InputStreamReader(process.getInputStream()))) {
                        String line;
                        while ((line = reader.readLine()) != null) {
                            output.append(line).append("\n");
                        }
                    }

                    int exitCode = process.waitFor();
                    if (exitCode == 0) {
                        //更新pg数据库字段
                        pgService.updateTable(layerInfo.getLayerName());
                        //将属性字段添加到字段表
                        desdTableColumnService.insertColumn(layerInfo.getLayerName());
                        log.info("图层 {} 上传成功，成功代码：{}\n输出：{}",
                                layerInfo.getLayerName(), exitCode, output);
                    } else {
                        log.error("图层 {} 上传失败，退出代码：{}\n输出：{}",
                                layerInfo.getLayerName(), exitCode, output);
                        allSuccess = false;
                    }
                } catch (Exception e) {
                    log.error("处理图层 {} 时发生错误", layerInfo.getLayerName(), e);
                    allSuccess = false;
                }
            }
            return allSuccess;
        } catch (Exception e) {
            log.error("上传过程中发生错误", e);
            return false;
        }
    }


    /**
     * 将GDB几何类型映射到PostgreSQL几何类型
     */
    private String mapGeometryType(String gdbGeometryType) {
        switch (gdbGeometryType.toUpperCase()) {
            case "POINT":
            case "MULTIPOINT":
                return "MULTIPOINT";
            case "LINESTRING":
            case "MULTILINESTRING":
                return "MULTILINESTRING";
            case "POLYGON":
            case "MULTIPOLYGON":
                return "MULTIPOLYGON";
            default:
                return "GEOMETRY";
        }
    }
}